5. Exercise: Proximity Analysis

소개

여러분은 위기 대응 팀의 일원이며, 뉴욕 시에서 병원들이 충돌 사고에 어떻게 대응해 왔는지를 확인하려고 합니다.

import math
import geopandas as gpd
import pandas as pd
from shapely.geometry import MultiPolygon

import folium
from folium import Choropleth, Marker
from folium.plugins import HeatMap, MarkerCluster
def embed_map(m, file_name):
    from IPython.display import IFrame
    m.save(file_name)
    return IFrame(file_name, width='100%', height='500px')

5-1. 충돌 데이터를 시각화합니다.

아래 코드 셀을 실행하여 2013-2018년의 주요 자동차 충돌을 추적하는 GeoDataFrame 충돌을 로드합니다.

collisions = gpd.read_file("C:/Users/Kangdaeyong/Desktop/datamining/kaggle_geospatial_analysis/archive/NYPD_Motor_Vehicle_Collisions/NYPD_Motor_Vehicle_Collisions/NYPD_Motor_Vehicle_Collisions.shp")
collisions.head()
DATE TIME BOROUGH ZIP CODE LATITUDE LONGITUDE LOCATION ON STREET CROSS STRE OFF STREET ... CONTRIBU_2 CONTRIBU_3 CONTRIBU_4 UNIQUE KEY VEHICLE TY VEHICLE _1 VEHICLE _2 VEHICLE _3 VEHICLE _4 geometry
0 07/30/2019 0:00 BRONX 10464 40.841100 -73.784960 (40.8411, -73.78496) None None 121 PILOT STREET ... Unspecified None None 4180045 Sedan Station Wagon/Sport Utility Vehicle Station Wagon/Sport Utility Vehicle None None POINT (1043750.211 245785.815)
1 07/30/2019 0:10 QUEENS 11423 40.710827 -73.770660 (40.710827, -73.77066) JAMAICA AVENUE 188 STREET None ... None None None 4180007 Sedan Sedan None None None POINT (1047831.185 198333.171)
2 07/30/2019 0:25 None None 40.880318 -73.841286 (40.880318, -73.841286) BOSTON ROAD None None ... None None None 4179575 Sedan Station Wagon/Sport Utility Vehicle None None None POINT (1028139.293 260041.178)
3 07/30/2019 0:35 MANHATTAN 10036 40.756744 -73.984590 (40.756744, -73.98459) None None 155 WEST 44 STREET ... None None None 4179544 Box Truck Station Wagon/Sport Utility Vehicle None None None POINT (988519.261 214979.320)
4 07/30/2019 10:00 BROOKLYN 11223 40.600090 -73.965910 (40.60009, -73.96591) AVENUE T OCEAN PARKWAY None ... None None None 4180660 Station Wagon/Sport Utility Vehicle Bike None None None POINT (993716.669 157907.212)

5 rows × 30 columns

"LATITUDE" 및 "LONGITUDE" 열을 사용하여 충돌 데이터를 시각화하는 대화형 지도를 만듭니다. 어떤 유형의 지도가 가장 효과적이라고 생각하십니까?

m_1 = folium.Map(location=[40.7, -74], zoom_start=11) 

# Your code here: Visualize the collision data
# Visualize the collision data
HeatMap(data=collisions[['LATITUDE', 'LONGITUDE']], radius=9).add_to(m_1)

m_1
Make this Notebook Trusted to load map: File -> Trust Notebook

5.2. 병원 보험 적용 범위를 파악합니다.

다음 코드 셀을 실행하여 병원 데이터를 로드합니다.

hospitals = gpd.read_file("C:/Users/Kangdaeyong/Desktop/datamining/kaggle_geospatial_analysis/archive/nyu_2451_34494/nyu_2451_34494/nyu_2451_34494.shp")
hospitals.head()
id name address zip factype facname capacity capname bcode xcoord ycoord latitude longitude geometry
0 317000001H1178 BRONX-LEBANON HOSPITAL CENTER - CONCOURSE DIVI... 1650 Grand Concourse 10457 3102 Hospital 415 Beds 36005 1008872.0 246596.0 40.843490 -73.911010 POINT (1008872.000 246596.000)
1 317000001H1164 BRONX-LEBANON HOSPITAL CENTER - FULTON DIVISION 1276 Fulton Ave 10456 3102 Hospital 164 Beds 36005 1011044.0 242204.0 40.831429 -73.903178 POINT (1011044.000 242204.000)
2 317000011H1175 CALVARY HOSPITAL INC 1740-70 Eastchester Rd 10461 3102 Hospital 225 Beds 36005 1027505.0 248287.0 40.848060 -73.843656 POINT (1027505.000 248287.000)
3 317000002H1165 JACOBI MEDICAL CENTER 1400 Pelham Pkwy 10461 3102 Hospital 457 Beds 36005 1027042.0 251065.0 40.855687 -73.845311 POINT (1027042.000 251065.000)
4 317000008H1172 LINCOLN MEDICAL & MENTAL HEALTH CENTER 234 E 149 St 10451 3102 Hospital 362 Beds 36005 1005154.0 236853.0 40.816758 -73.924478 POINT (1005154.000 236853.000)

"위도" 및 "경도" 열을 사용하여 병원 위치를 시각화합니다.

m_2 = folium.Map(location=[40.7, -74], zoom_start=11) 

# Your code here: Visualize the hospital locations
# Visualize the hospital locations
for idx, row in hospitals.iterrows():
    Marker([row['latitude'], row['longitude']], popup=row['name']).add_to(m_2)

# Uncomment to see a hint
#q_2.hint()
        
# Show the map
m_2
Make this Notebook Trusted to load map: File -> Trust Notebook

5.3. 가장 가까운 병원이 10km 이상 떨어진 때는 언제였습니까?

가장 가까운 병원에서 10km 이상 떨어진 곳에서 발생한 충돌 충돌의 모든 행을 포함하는 DataFrame outside_range를 만듭니다.

병원과 충돌 모두 좌표 참조 시스템으로 EPSG 2263이 있고 EPSG 2263에는 미터 단위가 있습니다.

outside_range = coverage = gpd.GeoDataFrame(geometry=hospitals.geometry).buffer(10000)
my_union = coverage.geometry.unary_union
outside_range = collisions.loc[~collisions["geometry"].apply(lambda x: my_union.contains(x))]

다음 코드 셀은 가장 가까운 병원에서 10km 이상 떨어진 곳에서 발생한 충돌의 비율을 계산합니다.

percentage = round(100*len(outside_range)/len(collisions), 2)
print("Percentage of collisions more than 10 km away from the closest hospital: {}%".format(percentage))
Percentage of collisions more than 10 km away from the closest hospital: 15.12%

5.4. 추천인을 만든다.

멀리 떨어진 곳에서 충돌이 발생하면 부상자를 가까운 병원으로 이송하는 것이 더욱 중요해집니다.

이를 염두에 두고 다음과 같은 추천자를 만들기로 결정합니다.

  • 충돌 위치(EPSG 2263)를 입력으로 사용합니다.
  • 가장 가까운 병원(거리 계산이 EPSG 2263에서 수행되는 곳)을 찾고,
  • 가장 가까운 병원의 이름을 반환합니다.
collisions.head()
DATE TIME BOROUGH ZIP CODE LATITUDE LONGITUDE LOCATION ON STREET CROSS STRE OFF STREET ... CONTRIBU_2 CONTRIBU_3 CONTRIBU_4 UNIQUE KEY VEHICLE TY VEHICLE _1 VEHICLE _2 VEHICLE _3 VEHICLE _4 geometry
0 07/30/2019 0:00 BRONX 10464 40.841100 -73.784960 (40.8411, -73.78496) None None 121 PILOT STREET ... Unspecified None None 4180045 Sedan Station Wagon/Sport Utility Vehicle Station Wagon/Sport Utility Vehicle None None POINT (1043750.211 245785.815)
1 07/30/2019 0:10 QUEENS 11423 40.710827 -73.770660 (40.710827, -73.77066) JAMAICA AVENUE 188 STREET None ... None None None 4180007 Sedan Sedan None None None POINT (1047831.185 198333.171)
2 07/30/2019 0:25 None None 40.880318 -73.841286 (40.880318, -73.841286) BOSTON ROAD None None ... None None None 4179575 Sedan Station Wagon/Sport Utility Vehicle None None None POINT (1028139.293 260041.178)
3 07/30/2019 0:35 MANHATTAN 10036 40.756744 -73.984590 (40.756744, -73.98459) None None 155 WEST 44 STREET ... None None None 4179544 Box Truck Station Wagon/Sport Utility Vehicle None None None POINT (988519.261 214979.320)
4 07/30/2019 10:00 BROOKLYN 11223 40.600090 -73.965910 (40.60009, -73.96591) AVENUE T OCEAN PARKWAY None ... None None None 4180660 Station Wagon/Sport Utility Vehicle Bike None None None POINT (993716.669 157907.212)

5 rows × 30 columns

def best_hospital(collision_location):
    idx_min = hospitals.geometry.distance(collision_location).idxmin()
    my_hospital = hospitals.iloc[idx_min]
    name = my_hospital["name"]
    return name

# Test your function: this should suggest CALVARY HOSPITAL INC
print(best_hospital(outside_range.geometry.iloc[0]))
CALVARY HOSPITAL INC

5.5. 수요가 가장 많은 병원은?

outside_range DataFrame에서 충돌만 고려한다면 어느 병원을 가장 추천하는가?

답은 4)에서 생성한 함수에서 반환한 병원 이름과 정확히 일치하는 Python 문자열이어야 합니다.

highest_demand = outside_range.geometry.apply(best_hospital).value_counts().idxmax()
highest_demand
'JAMAICA HOSPITAL MEDICAL CENTER'

5.6. 도시는 어디에 새 병원을 지어야 합니까?

다음 코드 셀(변경 없이)을 실행하여 가장 가까운 병원에서 10km 이상 떨어진 곳에서 발생한 충돌 외에도 병원 위치를 시각화합니다.

m_6 = folium.Map(location=[40.7, -74], zoom_start=11) 

coverage = gpd.GeoDataFrame(geometry=hospitals.geometry).buffer(10000)
folium.GeoJson(coverage.geometry.to_crs(epsg=4326)).add_to(m_6)
HeatMap(data=outside_range[['LATITUDE', 'LONGITUDE']], radius=9).add_to(m_6)
folium.LatLngPopup().add_to(m_6)

m_6
Make this Notebook Trusted to load map: File -> Trust Notebook

지도의 아무 곳이나 클릭하면 해당 위치의 위도 및 경도 팝업이 표시됩니다.

New York 시는 두 곳의 새로운 병원을 지을 위치를 결정하는 데 도움을 드리기 위해 연락을 드립니다. 그들은 특히 3) 단계에서 계산된 백분율을 10% 미만으로 만들기 위해 위치 식별에 대한 귀하의 도움을 원합니다. 지도를 사용하여(지역 설정법이나 병원을 건설하기 위해 제거해야 할 잠재적 건물에 대해 걱정하지 않고) 도시가 이 목표를 달성하는 데 도움이 되는 두 위치를 식별할 수 있습니까?

병원 1에 대해 제안된 위도와 경도를 각각 lat_1과 long_1에 넣습니다. (병원2도 마찬가지)

그런 다음 나머지 셀을 그대로 실행하여 새 병원의 효과를 확인하십시오. 두 개의 새로운 병원에서 백분율을 10% 미만으로 낮추면 답이 정답으로 표시됩니다.

lat_1 = 40.6714
long_1 = -73.8492

# Proposed location of hospital 2
lat_2 = 40.6702
long_2 = -73.7612

# Do not modify the code below this line
try:
    new_df = pd.DataFrame(
        {'Latitude': [lat_1, lat_2],
         'Longitude': [long_1, long_2]})
    new_gdf = gpd.GeoDataFrame(new_df, geometry=gpd.points_from_xy(new_df.Longitude, new_df.Latitude))
    new_gdf.crs = {'init' :'epsg:4326'}
    new_gdf = new_gdf.to_crs(epsg=2263)
    # get new percentage
    new_coverage = gpd.GeoDataFrame(geometry=new_gdf.geometry).buffer(10000)
    new_my_union = new_coverage.geometry.unary_union
    new_outside_range = outside_range.loc[~outside_range["geometry"].apply(lambda x: new_my_union.contains(x))]
    new_percentage = round(100*len(new_outside_range)/len(collisions), 2)
    print("(NEW) Percentage of collisions more than 10 km away from the closest hospital: {}%".format(new_percentage))
    # Did you help the city to meet its goal?
    q_6.check()
    # make the map
    m = folium.Map(location=[40.7, -74], zoom_start=11) 
    folium.GeoJson(coverage.geometry.to_crs(epsg=4326)).add_to(m)
    folium.GeoJson(new_coverage.geometry.to_crs(epsg=4326)).add_to(m)
    for idx, row in new_gdf.iterrows():
        Marker([row['Latitude'], row['Longitude']]).add_to(m)
    HeatMap(data=new_outside_range[['LATITUDE', 'LONGITUDE']], radius=9).add_to(m)
    folium.LatLngPopup().add_to(m)
    display(embed_map(m, 'q_6.html'))
except:
    print('a')
c:\Users\Kangdaeyong\anaconda3\lib\site-packages\pyproj\crs\crs.py:130: FutureWarning: '+init=<authority>:<code>' syntax is deprecated. '<authority>:<code>' is the preferred initialization method. When making the change, be mindful of axis order changes: https://pyproj4.github.io/pyproj/stable/gotchas.html#axis-order-changes-in-proj-6
  in_crs_string = _prepare_from_proj_string(in_crs_string)
(NEW) Percentage of collisions more than 10 km away from the closest hospital: 9.12%
a